#ifndef USER_H
#define USER_H

#include <sys/types.h>
#include <assert.h>
#include <string.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include "format.h"
#include "utility.h"


#ifdef __cplusplus
extern "C"
{
#endif //!__cplusplus

#define FILE_MODE (S_IRWXU |S_IRWXG | S_IRWXO)
#define SERVER_DATA_FILE "./data/server.data"
#define CLIENT_DATA_FILE "./data/client.data"
#define SHM_SERVER_NAME "./data/shm_server.data"
#define SHM_CLIENT_NAME "./data/shm_client.data"
#define CLIENT_WORK_PATH "./data"

#ifndef MAX_BUF_SIZE
#define MAX_BUF_SIZE 1024
#endif


#pragma pack(4)
enum UP_DOWN
{
    FILE_NONE = 0,
    FILE_DOWN,
    FILE_UP,
};
typedef struct
{
    uint8_t up_down;        //上传下载标志
    uint32_t file_size;     //文件总字节数
    uint32_t finished_size; //已经完成的字节数
    int8_t file_name[MAX_BUF_SIZE / 4];
    int8_t sha256[64]; //文件sha校验值
} FILE_TRANS_TASK;

typedef struct
{
    int8_t name[16];      //用户姓名，最长128字节
    int8_t passwd[16];    //用户密码
    u_int8_t session[16]; //每次登录时更新用作后续连接的验证
    int64_t m_timestamp;  //时间戳
    struct bufferevent *bev;
    FILE *fp;
    FILE_TRANS_TASK file_task;
} USER_DATA;

typedef struct
{
    pthread_mutex_t mutex;        //互斥锁
    u_int32_t user_number;        //用户总数
    u_int32_t online_user_number; //在线用户数量
    USER_DATA *user_data_addr;    //数据地址
} ALL_DATA;

extern ALL_DATA *g_all_data;

enum E_SOCK_TYPE
{
    SOCK_TYPE_STREAM = 0,
    SOCK_TYPE_DGRAM,
    SOCK_TYPE_BUFFERENT
};
typedef struct
{
    uint8_t m_sock_type;    //套接字类型
    int m_sockfd;           //句柄
    struct sockaddr_in m_in_addr;
    struct sockaddr m_addr; //UDP:recvfrom时初始化,sendto时需要用到
    socklen_t m_size;       //UDP:recvfrom时初始化,sendto时需要用到
    struct bufferevent *m_bev;  //libevent库封装过的读写句柄
} SOCK_BUFFER;

int server_file_path_init();
uint32_t add_user(SOCK_BUFFER *bev, char *name, char *passwd);
int user_data_mmap();
int create_rand_string(int num, char *string);
int create_rand_printable_string(char *string, int num);
int generatSession(u_int64_t id);

/**
 * @brief  初始化数据库
 * @note   检查user表是否存在,不存在则创建
 * @param  *dbName: 
 * @retval 
 */
int initDatabase();
#ifdef __cplusplus
}
#endif //!__cplusplus
#endif //!USER_H
